import React, { useState, useRef, useEffect } from 'react';

import './recorder.scss'

type RecorderState = {
  recording: boolean;
  audioURL: string;
  audioBlob: Blob | null;
  recordingTime: number;
  audioPlaying: boolean;
  permissionDenied: boolean;
};

const Recorder: React.FC = () => {
  // 状态管理
  const [state, setState] = useState<RecorderState>({
    recording: false,
    audioURL: '',
    audioBlob: null,
    recordingTime: 0,
    audioPlaying: false,
    permissionDenied: false
  });
  
  // Refs
  const mediaRecorderRef = useRef<MediaRecorder | null>(null);
  const audioChunksRef = useRef<Blob[]>([]);
  const timerRef = useRef<NodeJS.Timeout | null>(null);
  const audioRef = useRef<HTMLAudioElement>(null);
  
  // 简化状态访问
  const { recording, audioURL, audioBlob, recordingTime, audioPlaying, permissionDenied } = state;

  // 更新状态辅助函数
  const updateState = (partialState: Partial<RecorderState>) => {
    setState(prev => ({ ...prev, ...partialState }));
  };

  // 组件卸载时清除定时器
  useEffect(() => {
    return () => {
      if (timerRef.current) clearInterval(timerRef.current);
      if (audioURL) URL.revokeObjectURL(audioURL);
    };
  }, [audioURL]);

  // 请求麦克风权限
  const requestMicrophonePermission = async (): Promise<MediaStream | null> => {
    try {
      const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
      return stream;
    } catch (error) {
      console.error("麦克风访问被拒绝:", error);
      updateState({ permissionDenied: true });
      return null;
    }
  };

  // 开始录音
  const startRecording = async () => {
    if (recording) return;
    
    // 重置状态
    updateState({ 
      recording: true, 
      audioURL: '', 
      recordingTime: 0,
      audioPlaying: false
    });
    audioChunksRef.current = [];
    
    const stream = await requestMicrophonePermission();
    if (!stream) return;
    
    // 创建媒体录制器
    mediaRecorderRef.current = new MediaRecorder(stream);
    
    // 设置事件监听器
    mediaRecorderRef.current.ondataavailable = (event: BlobEvent) => {
      if (event.data.size > 0) {
        audioChunksRef.current.push(event.data);
      }
    };
    
    mediaRecorderRef.current.onstop = () => {
      // 创建音频Blob和URL
      const audioBlob = new Blob(audioChunksRef.current, { type: 'audio/wav' });
      
      const audioUrl = URL.createObjectURL(audioBlob);
      updateState({ audioURL: audioUrl, audioBlob });
      
      // 释放流资源
      stream.getTracks().forEach(track => track.stop());
    };
    
    // 开始录制
    mediaRecorderRef.current.start();
    
    // 启动计时器
    timerRef.current = setInterval(() => {
      setState(prev => ({ ...prev, recordingTime: prev.recordingTime + 1 }));
    }, 1000);
  };

  // 停止录音
  const stopRecording = () => {
    if (!recording || !mediaRecorderRef.current) return;
    
    if (timerRef.current) clearInterval(timerRef.current);
    updateState({ recording: false });
    mediaRecorderRef.current.stop();
    
  };

  // 播放录音
  const playRecordedAudio = () => {
    if (!audioURL || !audioRef.current) return;
    
    if (audioPlaying) {
      audioRef.current.pause();
      updateState({ audioPlaying: false });
      return;
    }
    
    audioRef.current.play();
    updateState({ audioPlaying: true });
    
    audioRef.current.onended = () => {
      updateState({ audioPlaying: false });
    };
  };

  // 下载录音
  const downloadRecording = () => {
    if (!audioBlob) return;
    
    const url = URL.createObjectURL(audioBlob);
    const a = document.createElement('a');
    a.style.display = 'none';
    a.href = url;
    a.download = `recording-${new Date().toISOString().slice(0, 19)}.wav`;
    document.body.appendChild(a);
    a.click();
    window.setTimeout(() => {
      document.body.removeChild(a);
      URL.revokeObjectURL(url);
    }, 100);
  };

  // 删除录音
  const deleteRecording = () => {
    if (audioURL) {
      URL.revokeObjectURL(audioURL);
    }
    updateState({ 
      audioURL: '',
      audioBlob: null,
      recordingTime: 0,
      audioPlaying: false
    });
  };

  // 格式化录音时间为 mm:ss
  const formatTime = (seconds: number): string => {
    const mins = Math.floor(seconds / 60);
    const secs = seconds % 60;
    return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
  };

  return (
    <div className="recorder-container">
      <div className="recorder-header">
        <h2>音频录制器</h2>
        <p className="recorder-description">
          使用此组件进行音频录制，录制完成后可以播放、下载或删除录音。
        </p>
      </div>

      <div className="recorder-controls">
        {!recording ? (
          <button 
            className="control-btn start-btn"
            onClick={startRecording}
            disabled={!!audioURL || permissionDenied}
          >
            <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
              <path d="M12 14c1.66 0 2.99-1.34 2.99-3L15 5c0-1.66-1.34-3-3-3S9 3.34 9 5v6c0 1.66 1.34 3 3 3zm5.3-3c0 3-2.54 5.1-5.3 5.1S6.7 14 6.7 11H5c0 3.41 2.72 6.23 6 6.72V21h2v-3.28c3.28-.48 6-3.3 6-6.72h-1.7z"/>
            </svg>
            开始录音
          </button>
        ) : (
          <button
            className="control-btn stop-btn"
            onClick={stopRecording}
          >
            <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
              <path d="M6 6h12v12H6z"/>
            </svg>
            停止录音
          </button>
        )}
      </div>

      {recording && (
        <div className="recording-indicator">
          <div className="pulsating-dot"></div>
          <span className="recording-text">录音中...</span>
          <span className="recording-time">{formatTime(recordingTime)}</span>
        </div>
      )}

      {permissionDenied && (
        <div className="permission-denied">
          <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
            <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"/>
          </svg>
          麦克风访问被拒绝。请在浏览器设置中允许麦克风访问并刷新页面。
        </div>
      )}

      {audioURL && !recording && (
        <div className="recorder-playback">
          <div className="audio-player">
            <audio 
              ref={audioRef} 
              src={audioURL} 
              preload="metadata"
              controls
              className="audio-element"
            />
          </div>
          
          <div className="playback-controls">
            <button 
              className={`control-btn ${audioPlaying ? 'pause-btn' : 'play-btn'}`}
              onClick={playRecordedAudio}
            >
              {audioPlaying ? (
                <>
                  <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
                    <path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z"/>
                  </svg>
                  暂停
                </>
              ) : (
                <>
                  <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
                    <path d="M8 5v14l11-7z"/>
                  </svg>
                  播放
                </>
              )}
            </button>
            
            <button 
              className="control-btn download-btn"
              onClick={downloadRecording}
            >
              <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
                <path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"/>
              </svg>
              下载
            </button>
            
            <button 
              className="control-btn delete-btn"
              onClick={deleteRecording}
            >
              <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
                <path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"/>
              </svg>
              删除
            </button>
          </div>
          
          <p className="recording-info">
            录音时长: {formatTime(recordingTime)} | 文件大小: {audioBlob ? Math.round(audioBlob.size / 1024) : 0}KB
          </p>
        </div>
      )}
    </div>
  );
};

export default Recorder;